package com.mojo.concurrent.concurrent_02_lock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * lock和condition 生产者消费者示例
 * 1、创建生产者，消费者，共享实例对象
 *
 * @author <a href="mailto:sjj@jianzhimao.com">mojo</a>
 * copyright (C), 2013-2022, 广州九尾信息科技有限公司
 * @date 2022/3/17 14:26
 */
public class LockCondition1 {
    public static void main(String[] args) {
        Thread pro = new Thread(new Pro());
        Thread sub = new Thread(new Sub());
        pro.start();
        sub.start();
    }
}

class Pro implements Runnable {

    @Override
    public void run() {
        while (true) {
            Resource.LOCK.lock();
            try {
                //有资源，等待
                if (Resource.hasResource) {
                    System.out.println(Resource.n);
                    Resource.CONDITION.await();
                }
                for (int i = 0; i < 50; i++) {
                    System.out.println(Thread.currentThread().getName() + "生产>>" + Resource.n++);
                }
                Resource.hasResource = true;
                Thread.sleep(1000L);
                //上产完毕，唤醒
                Resource.CONDITION.signalAll();

            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                Resource.LOCK.unlock();
            }
        }
    }
}

class Sub implements Runnable {

    @Override
    public void run() {
        while (true) {
            Resource.LOCK.lock();
            try {
                //无资源，等待
                if (!Resource.hasResource) {
                    System.out.println(">>>>>>>>>>>>>");
                    Resource.CONDITION.await();
                }
                for (int i = 0; i < 50; i++) {
                    System.out.println(Thread.currentThread().getName() + "消费>>" + Resource.n--);
                }
                Resource.hasResource = false;
                Thread.sleep(1000L);
                //消费完毕，唤醒
                Resource.CONDITION.signalAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                Resource.LOCK.unlock();
            }
        }
    }
}

class Resource {
    static Integer n = 0;
    final static Lock LOCK = new ReentrantLock();
    static boolean hasResource = false;
    final static Condition CONDITION = LOCK.newCondition();
}